/*****************************************************************************
 * Copyright (C) Stacy Curl. All rights reserved.                            *
 * ------------------------------------------------------------------------- *
 * The software in this package is published under the terms of the BSD      *
 * style license a copy of which has been included with this distribution in *
 * the LICENSE.txt file.                                                     *
 *****************************************************************************/
package picounit.features.test_instantiator;

import picounit.PicoUnitException;
import picounit.features.signature_factory.SignatureFactory;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

public class OrdinaryInstantiator implements Instantiator {
	private final SignatureFactory signatureFactory;

	public OrdinaryInstantiator(SignatureFactory signatureFactory) {
		this.signatureFactory = signatureFactory;
	}

	///////////////////////////////////////////////////////////////////////////////////////////////
	// Instantiator
	///////////////////////////////////////////////////////////////////////////////////////////////

	public <T> T instantiate(Class<T> toInstantiate) {
		try {
			return instantiateImpl(toInstantiate);
		}
		catch (PicoUnitException e) {
			throw e;
		}
		catch (Exception e) {
			throw new PicoUnitException(e);
		}
	}

	///////////////////////////////////////////////////////////////////////////////////////////////
	// Implementation
	///////////////////////////////////////////////////////////////////////////////////////////////

	@SuppressWarnings("unchecked")
	private <T> T instantiateImpl(Class<T> toInstantiate) throws InstantiationException,
		IllegalAccessException, InvocationTargetException {

		Constructor<T>[] constructors = toInstantiate.getConstructors();

		if (constructors.length == 0) {
			return toInstantiate.newInstance();
		}

		if (constructors.length != 1) {
			throw new PicoUnitException(toInstantiate.getName() +
				" has more than one public constructor");
		}

		Constructor<T> constructor = constructors[0];
		
//		System.out.println(String.format("instantiating: %s, classLoader: %s, with: %s", toInstantiate,
//			toInstantiate.getClassLoader(), this));

		return constructor.newInstance(
			signatureFactory.create(constructor).parameterValues());
	}
}
